home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / misc / MUser17src.lha / MultiUser / src / Library / Config.c next >
Encoding:
C/C++ Source or Header  |  1994-03-07  |  20.0 KB  |  841 lines

  1. /************************************************************
  2. * MultiUser - MultiUser Task/File Support System                *
  3. * ---------------------------------------------------------    *
  4. * Configuration                                                            *
  5. * ---------------------------------------------------------    *
  6. * © Copyright 1993-1994 by Geert Uytterhoeven                    *
  7. * All Rights Reserved.                                                    *
  8. ************************************************************/
  9.  
  10.  
  11. #include <exec/alerts.h>
  12. #include <exec/execbase.h>
  13. #include <dos/dos.h>
  14. #include <dos/filehandler.h>
  15. #include <libraries/reqtools.h>
  16. #include <proto/exec.h>
  17. #include <proto/dos.h>
  18. #include <proto/reqtools.h>
  19. #include <string.h>
  20.  
  21. #include "Memory.h"
  22. #include "Misc.h"
  23. #include "Config.h"
  24. #include "LibHeader.h"
  25.  
  26.  
  27.     /*
  28.      *        Static Routines
  29.      */
  30.  
  31. static void ClearBuffer(void);
  32. static void InitDefs(void);
  33. static struct muUserDef *ParseUserLine(STRPTR line, ULONG linenum);
  34. static struct muGroupDef *ParseGroupLine(STRPTR line, ULONG linenum);
  35. static void ParseRelationLine(STRPTR line, ULONG linenum);
  36. static BOOL ReadKeyFiles(void);
  37. static BOOL ReadKeyFile(struct MsgPort *fs);
  38. static BOOL ParseDirLockLine(struct MsgPort *fs, BPTR file, BPTR *dir);
  39. static void RemTerminatingLF(char *buffer);
  40. static void LoadConfig(void);
  41. static STRPTR SafeFGets(BPTR fh, STRPTR buf, ULONG len);
  42.  
  43.  
  44.     /*
  45.      *        Configuration Stuff
  46.      */
  47.  
  48. char KeyFileName[] = muKey_FileName;
  49. char PasswdFileName[] = muPasswd_FileName;
  50. char ConfigFileName[] = muConfig_FileName;
  51. char GroupFileName[] = muGroup_FileName;
  52. char LogFileName[] = muLog_FileName;
  53. BPTR PasswdDirLock = NULL;
  54. BPTR ConfigDirLock = NULL;
  55. struct muUserDef *UserDef = NULL;
  56. struct muGroupDef *GroupDef = NULL;
  57. char Key[12];
  58. BOOL FirstStartup = TRUE;
  59.  
  60.  
  61.     /*
  62.      *        General Purpose Buffer
  63.      */
  64.  
  65. #define GENBUFSIZE 1024
  66.  
  67. char *Buffer = NULL;
  68.  
  69.  
  70.     /*
  71.      *        Passwd and Group File Notification
  72.      */
  73.  
  74. struct NotifyRequest __aligned PasswdNotifyReq;
  75. struct NotifyRequest __aligned GroupNotifyReq;
  76.  
  77.  
  78.     /*
  79.      *        Clear the General Purpose Buffer
  80.      */
  81.  
  82. static void __inline ClearBuffer(void)
  83. {
  84.     memset(Buffer, NULL, GENBUFSIZE);
  85. }
  86.  
  87.  
  88.     /*
  89.      *        Get a pointer to the User Definitions
  90.      */
  91.  
  92. struct muUserDef *GetUserDefs(void)
  93. {
  94.     if (!UserDef)
  95.         InitDefs();
  96.     return(UserDef);
  97. }
  98.  
  99.  
  100.     /*
  101.      *        Get a pointer to the Group Definitions
  102.      */
  103.  
  104. struct muGroupDef *GetGroupDefs(void)
  105. {
  106.     if (!GroupDef)
  107.         InitDefs();
  108.     return(GroupDef);
  109. }
  110.  
  111.  
  112.     /*
  113.      *        Initialise the User and Group Definitions
  114.      */
  115.  
  116. static void InitDefs(void)
  117. {
  118.     BPTR file;
  119.     ULONG linenum;
  120.  
  121.     CurrentDir(PasswdDirLock);
  122.     if (file = Open(PasswdFileName, MODE_OLDFILE)) {
  123.         struct muUserDef *def1, *def2 = NULL;
  124.  
  125.         for (linenum = 1; FGets(file, Buffer, GENBUFSIZE-1); linenum++)
  126.                       /* V36/37: use GENBUFSIZE-1 */
  127.                       /* V39: use GENBUFSIZE */
  128.             if (Buffer[0] && (Buffer[0] != '\n'))
  129.                 if (def1 = ParseUserLine(Buffer, linenum)) {
  130.                     if (def2)
  131.                         def2->Next = def1;
  132.                     else
  133.                         UserDef = def1;
  134.                     def2 = def1;
  135.                 }
  136.         Close(file);
  137.     }
  138.     CurrentDir(ConfigDirLock);
  139.     if (UserDef && (file = Open(GroupFileName, MODE_OLDFILE))) {
  140.         struct muGroupDef *def1, *def2 = NULL;
  141.  
  142.         for (linenum = 1; FGets(file, Buffer, GENBUFSIZE-1) && (Buffer[0] != '\n'); linenum++)
  143.                       /* V36/37: use GENBUFSIZE-1 */
  144.                       /* V39: use GENBUFSIZE */
  145.             if (Buffer[0])
  146.                 if (def1 = ParseGroupLine(Buffer, linenum)) {
  147.                     if (def2)
  148.                         def2->Next = def1;
  149.                     else
  150.                         GroupDef = def1;
  151.                     def2 = def1;
  152.                 }
  153.         if (Buffer[0] == '\n')
  154.             for (linenum++; FGets(file, Buffer, GENBUFSIZE-1); linenum++)
  155.                           /* V36/37: use GENBUFSIZE-1 */
  156.                           /* V39: use GENBUFSIZE */
  157.                 if (Buffer[0] && (Buffer[0] != '\n'))
  158.                     ParseRelationLine(Buffer, linenum);
  159.         Close(file);
  160.     }
  161.     ClearBuffer();
  162.  
  163.     if (!UserDef || !GroupDef)
  164.         FreeDefs();
  165. }
  166.  
  167.  
  168.     /*
  169.      *        Parse a User Entry
  170.      */
  171.  
  172. static struct muUserDef *ParseUserLine(STRPTR line, ULONG linenum)
  173. {
  174.     int i, j, len;
  175.     LONG uid, gid;
  176.     struct muUserDef *def;
  177.     STRPTR part[7];
  178.     STRPTR ptr;
  179.  
  180.     #define UPART_USERID        0
  181.     #define UPART_PASSWORD    1
  182.     #define UPART_UID            2
  183.     #define UPART_GID            3
  184.     #define UPART_USERNAME    4
  185.     #define UPART_HOMEDIR    5
  186.     #define UPART_SHELL        6
  187.  
  188.     i = 0;
  189.     for (j = 0; j < 7; j++) {
  190.         part[j] = &line[i];
  191.         while ((line[i]) && (line[i] != '\n') && (line[i] != '|'))
  192.             i++;
  193.         if (j == 6)
  194.             if (line[i] && (line[i] != '\n'))
  195.                 goto Fail;
  196.             else {}
  197.         else if (line[i] != '|')
  198.             goto Fail;
  199.         line[i++] = '\0';
  200.         len = strlen(part[j]);
  201.         switch(j) {
  202.             case UPART_USERID:
  203.                 if (!len)
  204.                     goto Fail;
  205.                 break;
  206.  
  207.             case UPART_PASSWORD:
  208.                 if (len && (len != 11))
  209.                     goto Fail;
  210.                 break;
  211.  
  212.             case UPART_UID:
  213.                 if (!len || (StrToLong(part[j], &uid) == -1) || (uid < 1) || (uid > 65535))
  214.                     goto Fail;
  215.                 break;
  216.  
  217.             case UPART_GID:
  218.                 if (!len || (StrToLong(part[j], &gid) == -1) || (gid < 0) || (gid > 65535))
  219.                     goto Fail;
  220.                 break;
  221.  
  222.             case UPART_USERNAME:
  223.             case UPART_HOMEDIR:
  224.             case UPART_SHELL:
  225.                 break;
  226.         }
  227.     }
  228.  
  229.     if (def = (struct muUserDef *)MAllocV(sizeof(struct muUserDef)+strlen(part[UPART_USERID])+
  230.                                                       strlen(part[UPART_USERNAME])+strlen(part[UPART_HOMEDIR])+
  231.                                                       strlen(part[UPART_SHELL])+16)) {
  232.         ptr = &((STRPTR)def)[sizeof(struct muUserDef)];
  233.         def->UserID = ptr;
  234.         strcpy(ptr, part[UPART_USERID]);
  235.         ptr = &ptr[strlen(part[UPART_USERID])+1];
  236.         def->Password = ptr;
  237.         strcpy(ptr, part[UPART_PASSWORD]);
  238.         ptr = &ptr[12];
  239.         def->uid = (UWORD)uid;
  240.         def->gid = (UWORD)gid;
  241.         def->UserName = ptr;
  242.         strcpy(ptr, part[UPART_USERNAME]);
  243.         ptr = &ptr[strlen(part[UPART_USERNAME])+1];
  244.         def->HomeDir = ptr;
  245.         strcpy(ptr, part[UPART_HOMEDIR]);
  246.         ptr = &ptr[strlen(part[UPART_HOMEDIR])+1];
  247.         def->Shell = ptr;
  248.         strcpy(ptr, part[UPART_SHELL]);
  249.     } else
  250.         Die(NULL, AN_Unknown | AG_NoMemory);
  251.     return(def);
  252.  
  253. Fail:
  254.     Warn("Bad entry found on line %ld of the password file\nThis line will be ignored", &linenum);
  255.     return(NULL);
  256. }
  257.  
  258.  
  259.     /*
  260.      *        Parse a Group Entry
  261.      */
  262.  
  263. static struct muGroupDef *ParseGroupLine(STRPTR line, ULONG linenum)
  264. {
  265.     int i, j, len;
  266.     LONG gid, mgruid;
  267.     struct muGroupDef *def;
  268.     STRPTR part[4];
  269.     STRPTR ptr;
  270.  
  271.     #define GPART_GROUPID    0
  272.     #define GPART_GID            1
  273.     #define GPART_MGRUID        2
  274.     #define GPART_GROUPNAME    3
  275.  
  276.     i = 0;
  277.     for (j = 0; j < 4; j++) {
  278.         part[j] = &line[i];
  279.         while ((line[i]) && (line[i] != '\n') && (line[i] != '|'))
  280.             i++;
  281.         if (j == 3)
  282.             if (line[i] && (line[i] != '\n'))
  283.                 goto Fail;
  284.             else {}
  285.         else if (line[i] != '|')
  286.             goto Fail;
  287.         line[i++] = '\0';
  288.         len = strlen(part[j]);
  289.         switch(j) {
  290.             case GPART_GROUPID:
  291.                 if (!len)
  292.                     goto Fail;
  293.                 break;
  294.  
  295.             case GPART_GID:
  296.                 if (!len || (StrToLong(part[j], &gid) == -1) || (gid < 0) || (gid > 65535))
  297.                     goto Fail;
  298.                 break;
  299.  
  300.             case GPART_MGRUID:
  301.                 if (!len || (StrToLong(part[j], &mgruid) == -1) || (mgruid < 0) || (mgruid > 65535))
  302.                     goto Fail;
  303.                 break;
  304.  
  305.             case GPART_GROUPNAME:
  306.                 break;
  307.         }
  308.     }
  309.  
  310.     if (def = (struct muGroupDef *)MAllocV(sizeof(struct muGroupDef)+strlen(part[GPART_GROUPID])+
  311.                                                         strlen(part[GPART_GROUPNAME])+2)) {
  312.         ptr = &((STRPTR)def)[sizeof(struct muGroupDef)];
  313.         def->GroupID = ptr;
  314.         strcpy(ptr, part[GPART_GROUPID]);
  315.         ptr = &ptr[strlen(part[GPART_GROUPID])+1];
  316.         def->gid = (UWORD)gid;
  317.         def->MgrUid = (UWORD)mgruid;
  318.         def->GroupName = ptr;
  319.         strcpy(ptr, part[GPART_GROUPNAME]);
  320.     } else
  321.         Die(NULL, AN_Unknown | AG_NoMemory);
  322.     return(def);
  323.  
  324. Fail:
  325.     Warn("Bad entry found on line %ld of the group file\nThis line will be ignored", &linenum);
  326.     return(NULL);
  327. }
  328.  
  329.  
  330.     /*
  331.      *        Parse a Relation Entry
  332.      */
  333.  
  334. static void ParseRelationLine(STRPTR line, ULONG linenum)
  335. {
  336.     struct muUserDef *def;
  337.     UWORD *groups;
  338.     ULONG numgroups = 0;
  339.     LONG uid, gid, len;
  340.     ULONG i, j;
  341.  
  342.     if (((len = StrToLong(line, &uid)) == -1) || (uid < 1) || (uid > 65535))
  343.         goto Fail;
  344.     i = len;
  345.     j = i+1;
  346.     if (line[i] != ':')
  347.         goto Fail;
  348.     for (def = UserDef; def && (def->uid != uid); def = def->Next);
  349.     if (def) {
  350.         do {
  351.             if (((len = StrToLong(&line[++i], &gid)) == -1) || (gid < 0) || (gid > 65535))
  352.                 goto Fail;
  353.             i += len;
  354.             numgroups++;
  355.             if (line[i] && (line[i] != ',') && (line[i] != '\n'))
  356.                 goto Fail;
  357.         } while (line[i] && (line[i] != '\n'));
  358.         if (def->NumSecGroups+numgroups <= 65535) {
  359.             if (def->NumSecGroups)
  360.                 if (groups = MAlloc((numgroups+def->NumSecGroups)*sizeof(UWORD))) {
  361.                     CopyMem(def->SecGroups, groups, def->NumSecGroups*sizeof(UWORD));
  362.                     Free(def->SecGroups, def->NumSecGroups*sizeof(UWORD));
  363.                     def->SecGroups = groups;
  364.                     groups += def->NumSecGroups;
  365.                     def->NumSecGroups += numgroups;
  366.                 } else
  367.                     Die(NULL, AN_Unknown | AG_NoMemory);
  368.             else if (groups = MAlloc(numgroups*sizeof(UWORD))) {
  369.                 def->SecGroups = groups;
  370.                 def->NumSecGroups = numgroups;
  371.             } else
  372.                 Die(NULL, AN_Unknown | AG_NoMemory);
  373.             if (groups)
  374.                 for (i = 0; i < numgroups; i++) {
  375.                     j += StrToLong(&line[j++], &gid);
  376.                     groups[i] = gid;
  377.                 }
  378.         } else {
  379.             LONG args[2];
  380.  
  381.             args[0] = uid;
  382.             args[1] = linenum;
  383.             Warn("Too many secondary groups for user with uid %ld\n"
  384.                   "Line %ld of the group file will be ignored", args);
  385.         }
  386.     } else
  387. Fail:
  388.     Warn("Bad entry found on line %ld of the group file\nThis line will be ignored", &linenum);
  389. }
  390.  
  391.  
  392.     /*
  393.      *        Free the User and Group Definitions
  394.      */
  395.  
  396. void FreeDefs(void)
  397. {
  398.     struct muUserDef *udef = UserDef;
  399.     struct muGroupDef *gdef = GroupDef;
  400.     APTR p;
  401.  
  402.     while(udef) {
  403.         p = udef->Next;
  404.         if (udef->NumSecGroups)
  405.             Free(udef->SecGroups, udef->NumSecGroups*sizeof(UWORD));
  406.         FreeV(udef);
  407.         udef = p;
  408.     }
  409.     UserDef = NULL;
  410.     while(gdef) {
  411.         p = gdef->Next;
  412.         FreeV(gdef);
  413.         gdef = p;
  414.     }
  415.     GroupDef = NULL;
  416. }
  417.  
  418.  
  419.     /*
  420.      *        Update the User Definitions
  421.      *
  422.      *
  423.      *        OUT:    BOOL    Success
  424.      */
  425.  
  426. BOOL UpdateUserDefs(void)
  427. {
  428.     BPTR file;
  429.     BOOL res;
  430.     struct muUserDef *def = UserDef;
  431.     LONG args[7];
  432.  
  433.     CurrentDir(PasswdDirLock);
  434.     if (res = (file = Open(PasswdFileName, MODE_NEWFILE))) {
  435.         while(def && res) {
  436.             args[0] = (LONG)def->UserID;
  437.             args[1] = (LONG)def->Password;
  438.             args[2] = (LONG)def->uid;
  439.             args[3] = (LONG)def->gid;
  440.             args[4] = (LONG)def->UserName;
  441.             args[5] = (LONG)def->HomeDir;
  442.             args[6] = (LONG)def->Shell;
  443.             res = (VFPrintf(file, "%s|%s|%ld|%ld|%s|%s|%s\n", args) != -1);
  444.             def = def->Next;
  445.         }
  446.         res = Close(file) && res;
  447.     }
  448.  
  449.     return(res);
  450. }
  451.  
  452.  
  453.     /*
  454.      *        Find all MultiUserFileSystem volumes
  455.      */
  456.  
  457. static BOOL FindVolumes(void)
  458. {
  459.     struct DosList *dl;
  460.     struct FileSysStartupMsg *sm;
  461.     struct DosEnvec *de;
  462.     BOOL res = FALSE;
  463.     struct muVolume **vollist = &muBase->Volumes;
  464.  
  465.     dl = LockDosList(LDF_DEVICES|LDF_READ);
  466.     while (dl = NextDosEntry(dl,LDF_DEVICES))
  467.         if ((dl->dol_Task) && ((LONG)(sm = BADDR(dl->dol_misc.dol_handler.dol_Startup)) > 1024) &&
  468.              (de = BADDR(sm->fssm_Environ)) && (de->de_TableSize >= DE_DOSTYPE) &&
  469.              (de->de_DosType == ID_MUFS_DISK))
  470.             if (*vollist = (struct muVolume *)MAlloc(sizeof(struct muVolume))) {
  471.                 (*vollist)->DosList = dl;
  472.                 (*vollist)->Process = dl->dol_Task;
  473.                 vollist = &(*vollist)->Next;
  474.                 res = TRUE;
  475.             } else
  476.                 Die(NULL, AN_Unknown | AG_NoMemory);
  477.     UnLockDosList(LDF_DEVICES|LDF_READ);
  478.     return(res);
  479. }
  480.  
  481.  
  482.     /*
  483.      *        Read and parse the Key Files
  484.      */
  485.  
  486. static BOOL ReadKeyFiles(void)
  487. {
  488.     struct muVolume *vol;
  489.     BOOL res = FALSE;
  490.  
  491.         for (vol = muBase->Volumes; vol && (res = ReadKeyFile(vol->Process)); vol = vol->Next);
  492.     return((BOOL)(res && PasswdDirLock && ConfigDirLock));
  493. }
  494.  
  495.  
  496. static BOOL ReadKeyFile(struct MsgPort *fs)
  497. {
  498.     BPTR dir, file;
  499.     char buffer[12];
  500.     BOOL res;
  501.     static char __aligned name[] = "\1:";
  502.  
  503.     if (res = (dir = DoPkt(fs, ACTION_LOCATE_OBJECT, NULL, MKBADDR(name), ACCESS_READ, NULL, NULL))) {
  504.         CurrentDir(dir);
  505.         if (res = (file = Open(KeyFileName, MODE_OLDFILE))) {
  506.             if (res = (BOOL)SafeFGets(file, Buffer, GENBUFSIZE-1)) {
  507.                                  /* V36/37: use GENBUFSIZE-1 */
  508.                                  /* V39: use GENBUFSIZE */
  509.                 RemTerminatingLF(Buffer);
  510.                 if (Encrypt(buffer, Buffer, "Alpha, PowerPC or R4400?")) {
  511.                     if (Key[0])
  512.                         res = !strcmp(Key, buffer);
  513.                     else
  514.                         strcpy(Key, buffer);
  515.                     if (res)
  516.                         res = ParseDirLockLine(fs, file, &PasswdDirLock) &&
  517.                                 ParseDirLockLine(fs, file, &ConfigDirLock);
  518.                 }
  519.             }
  520.             Close(file);
  521.             ClearBuffer();
  522.         }
  523.         UnLock(dir);
  524.     }
  525.     return(res);
  526. }
  527.  
  528.  
  529.     /*
  530.      *        Parse a Key File Line and Lock the appropriate Directory
  531.      */
  532.  
  533. static BOOL ParseDirLockLine(struct MsgPort *fs, BPTR file, BPTR *dir)
  534. {
  535.     BOOL res;
  536.  
  537.     if (res = (BOOL)FGets(file, Buffer+1, GENBUFSIZE-2)) {
  538.                          /* V36/37: use GENBUFSIZE-2 */
  539.                          /* V39: use GENBUFSIZE-1 */
  540.         RemTerminatingLF(Buffer);
  541.         if (Buffer[1])
  542.             if (*dir)
  543.                 res = FALSE;
  544.             else {
  545.                 Buffer[0] = strlen(Buffer+1);
  546.                 res = *dir = DoPkt(fs, ACTION_LOCATE_OBJECT, NULL, MKBADDR(Buffer), ACCESS_READ, NULL, NULL);
  547.             }
  548.     }
  549.     return(res);
  550. }
  551.  
  552.  
  553. static void RemTerminatingLF(char *buffer)
  554. {
  555.     int i;
  556.  
  557.     for (i = 0; buffer[i]; i++);
  558.     if (i && (buffer[i-1] == '\n'))
  559.         buffer[i-1] = '\0';
  560. }
  561.  
  562.  
  563.     /*
  564.      *        Load the Configuration file
  565.      */
  566.  
  567. static void LoadConfig(void)
  568. {
  569.     BPTR file;
  570.     LONG *argarray[12];
  571.  
  572. #define argLIMITDOSSETPROTECTION    0
  573. #define argPROFILE                    1
  574. #define argLASTLOGINREQ                2
  575. #define argLOGSTARTUP                3
  576. #define argLOGLOGIN                    4
  577. #define argLOGLOGINFAIL                5
  578. #define argLOGPASSWD                    6
  579. #define argLOGPASSWDFAIL            7
  580. #define argLOGCHECKPASSWD            8
  581. #define argLOGCHECKPASSWDFAIL        9
  582. #define argPASSWDUIDLEVEL            10
  583. #define argPASSWDGIDLEVEL            11
  584.  
  585.     struct RDArgs *rdargs;
  586.     ULONG line;
  587.     struct muConfig config;
  588.  
  589.     config.Flags = muCFGF_LimitDOSSetProtection | muCFGF_Profile | muCFGF_LastLoginReq;
  590.     config.LogFlags = NULL;
  591.     config.PasswduidLevel = 0;
  592.     config.PasswdgidLevel = 0;
  593.  
  594.     if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  595.         CurrentDir(ConfigDirLock);
  596.         if (file = Open(ConfigFileName, MODE_OLDFILE)) {
  597.             for (line = 1; FGets(file, Buffer, GENBUFSIZE-1); line++) {
  598.                               /* V36/37: use GENBUFSIZE-1 */
  599.                               /* V39: use GENBUFSIZE */
  600.                 rdargs->RDA_Source.CS_Buffer = Buffer;
  601.                 rdargs->RDA_Source.CS_Length = strlen(Buffer);
  602.                 rdargs->RDA_Source.CS_CurChr = 0;
  603.                 rdargs->RDA_DAList = NULL;
  604.                 rdargs->RDA_Buffer = NULL;
  605.                 rdargs->RDA_BufSiz = NULL;
  606.                 rdargs->RDA_ExtHelp = NULL;
  607.                 rdargs->RDA_Flags = RDAF_NOPROMPT;
  608.                 memset(argarray, NULL, sizeof(argarray));
  609.                 if (ReadArgs("LIMITDOSSETPROTECTION/K/N,PROFILE/K/N,LASTLOGINREQ/K/N,LOGSTARTUP/K/N,"
  610.                                  "LOGLOGIN/K/N,LOGLOGINFAIL/K/N,LOGPASSWD/K/N,LOGPASSWDFAIL/K/N,"
  611.                                  "LOGCHECKPASSWD/K/N,LOGCHECKPASSWDFAIL/K/N,PASSWDUIDLEVEL/K/N,"
  612.                                  "PASSWDGIDLEVEL/K/N", (LONG *)argarray, rdargs)) {
  613.                     if (argarray[argLIMITDOSSETPROTECTION])
  614.                         if (*argarray[argLIMITDOSSETPROTECTION])
  615.                             config.Flags |= muCFGF_LimitDOSSetProtection;
  616.                         else
  617.                             config.Flags &= ~muCFGF_LimitDOSSetProtection;
  618.                     if (argarray[argPROFILE])
  619.                         if (*argarray[argPROFILE])
  620.                             config.Flags |= muCFGF_Profile;
  621.                         else
  622.                             config.Flags &= ~muCFGF_Profile;
  623.                     if (argarray[argLASTLOGINREQ])
  624.                         if (*argarray[argLASTLOGINREQ])
  625.                             config.Flags |= muCFGF_LastLoginReq;
  626.                         else
  627.                             config.Flags &= ~muCFGF_LastLoginReq;
  628.                     if (argarray[argLOGSTARTUP])
  629.                         if (*argarray[argLOGSTARTUP])
  630.                             config.LogFlags |= muLogF_Startup;
  631.                         else
  632.                             config.LogFlags &= ~muLogF_Startup;
  633.                     if (argarray[argLOGLOGIN])
  634.                         if (*argarray[argLOGLOGIN])
  635.                             config.LogFlags |= muLogF_Login;
  636.                         else
  637.                             config.LogFlags &= ~muLogF_Login;
  638.                     if (argarray[argLOGLOGINFAIL])
  639.                         if (*argarray[argLOGLOGINFAIL])
  640.                             config.LogFlags |= muLogF_LoginFail;
  641.                         else
  642.                             config.LogFlags &= ~muLogF_LoginFail;
  643.                     if (argarray[argLOGPASSWD])
  644.                         if (*argarray[argLOGPASSWD])
  645.                             config.LogFlags |= muLogF_Passwd;
  646.                         else
  647.                             config.LogFlags &= ~muLogF_Passwd;
  648.                     if (argarray[argLOGPASSWDFAIL])
  649.                         if (*argarray[argLOGPASSWDFAIL])
  650.                             config.LogFlags |= muLogF_PasswdFail;
  651.                         else
  652.                             config.LogFlags &= ~muLogF_PasswdFail;
  653.                     if (argarray[argLOGCHECKPASSWD])
  654.                         if (*argarray[argLOGCHECKPASSWD])
  655.                             config.LogFlags |= muLogF_CheckPasswd;
  656.                         else
  657.                             config.LogFlags &= ~muLogF_CheckPasswd;
  658.                     if (argarray[argLOGCHECKPASSWDFAIL])
  659.                         if (*argarray[argLOGCHECKPASSWDFAIL])
  660.                             config.LogFlags |= muLogF_CheckPasswdFail;
  661.                         else
  662.                             config.LogFlags &= ~muLogF_CheckPasswdFail;
  663.                     if (argarray[argPASSWDUIDLEVEL])
  664.                         if (*argarray[argPASSWDUIDLEVEL] > 65535)
  665.                             Warn("Bad value(s) found on line %ld of the configuration file\n"
  666.                                   "This value will be ignored", &line);
  667.                         else
  668.                             config.PasswduidLevel = *argarray[argPASSWDUIDLEVEL];
  669.                     if (argarray[argPASSWDGIDLEVEL])
  670.                         if (*argarray[argPASSWDGIDLEVEL] > 65535)
  671.                             Warn("Bad value(s) found on line %ld of the configuration file\n"
  672.                                   "This value will be ignored", &line);
  673.                         else
  674.                             config.PasswdgidLevel = *argarray[argPASSWDGIDLEVEL];
  675.                 } else
  676.                     Warn("Bad option found on line %ld of the configuration file\n"
  677.                           "This line will be ignored", &line);
  678.                 FreeArgs(rdargs);
  679.             }
  680.             Close(file);
  681.             ClearBuffer();
  682.         } else
  683.             Warn("Couldn't load the configuration file\nUsing the default configuration", NULL);
  684.         FreeDosObject(DOS_RDARGS, rdargs);
  685.     } else
  686.         Die(NULL, AN_Unknown | AG_NoMemory);
  687.  
  688.     muBase->Config.Flags = config.Flags;
  689.     muBase->Config.LogFlags = config.LogFlags;
  690.     muBase->Config.PasswduidLevel = config.PasswduidLevel;
  691.     muBase->Config.PasswdgidLevel = config.PasswdgidLevel;
  692.  
  693.     if (FirstStartup) {
  694.         FirstStartup = FALSE;
  695.         if (muBase->Config.LogFlags & muLogF_Startup)
  696.             VLogF("Startup", NULL);
  697.     }
  698. }
  699.  
  700.  
  701.     /*
  702.      *        Initialise the Volume Information
  703.      */
  704.  
  705. BOOL InitVolumes(void)
  706. {
  707.     if (!(Buffer = MAlloc(GENBUFSIZE)))
  708.         Die(NULL, AN_Unknown | AG_NoMemory);
  709.     ObtainSemaphore(&muBase->VolumesSem);
  710.     if (!FindVolumes())
  711.         Die("You must have at least one partition with the MultiUserFileSystem", NULL);
  712.     if (!ReadKeyFiles()) {
  713.         muBase->SecurityViolation = TRUE;
  714.         Die("Security violation: Bad or inconsistent keyfile(s) found", NULL);
  715.     }
  716.     ReleaseSemaphore(&muBase->VolumesSem);
  717.     LoadConfig();
  718.     CurrentDir(PasswdDirLock);        
  719.     memset(&PasswdNotifyReq, NULL, sizeof(PasswdNotifyReq));
  720.     PasswdNotifyReq.nr_Name = PasswdFileName;
  721.     PasswdNotifyReq.nr_Flags = NRF_SEND_SIGNAL;
  722.     PasswdNotifyReq.nr_stuff.nr_Signal.nr_Task = (struct Task *)SysBase->ThisTask;
  723.     PasswdNotifyReq.nr_stuff.nr_Signal.nr_SignalNum = muBase->NotifySig;
  724.     StartNotify(&PasswdNotifyReq);
  725.     CurrentDir(ConfigDirLock);        
  726.     memset(&GroupNotifyReq, NULL, sizeof(GroupNotifyReq));
  727.     GroupNotifyReq.nr_Name = GroupFileName;
  728.     GroupNotifyReq.nr_Flags = NRF_SEND_SIGNAL;
  729.     GroupNotifyReq.nr_stuff.nr_Signal.nr_Task = (struct Task *)SysBase->ThisTask;
  730.     GroupNotifyReq.nr_stuff.nr_Signal.nr_SignalNum = muBase->NotifySig;
  731.     StartNotify(&GroupNotifyReq);
  732.     return(TRUE);
  733. }
  734.  
  735.  
  736.     /*
  737.      *        Free all Volume Information
  738.      */
  739.  
  740. void FreeVolumes(void)
  741. {
  742.     struct muVolume *vollist, *vl2;
  743.  
  744.     FreeDefs();
  745.     EndNotify(&GroupNotifyReq);
  746.     EndNotify(&PasswdNotifyReq);
  747.     if (PasswdDirLock) {
  748.         UnLock(PasswdDirLock);
  749.         PasswdDirLock = NULL;
  750.     }
  751.     if (ConfigDirLock) {
  752.         UnLock(ConfigDirLock);
  753.         ConfigDirLock = NULL;
  754.     }
  755.     ObtainSemaphore(&muBase->VolumesSem);
  756.     vollist = muBase->Volumes;
  757.     while (vollist) {
  758.         vl2 = vollist->Next;
  759.         Free(vollist, sizeof(struct muVolume));
  760.         vollist = vl2;
  761.     }
  762.     muBase->Volumes = NULL;
  763.     ReleaseSemaphore(&muBase->VolumesSem);
  764.     memset(Key, NULL, sizeof(Key));
  765.     if (Buffer) {
  766.         Free(Buffer, GENBUFSIZE);
  767.         Buffer = NULL;
  768.     }
  769. }
  770.  
  771.  
  772.     /*
  773.      *        Check whether a Process belongs to a muFS Volume
  774.      */
  775.  
  776. BOOL CheckmuFSVolume(struct MsgPort *port)
  777. {
  778.     struct muVolume *vollist;
  779.     BOOL res = FALSE;
  780.  
  781.     ObtainSemaphoreShared(&muBase->VolumesSem);
  782.     for (vollist = muBase->Volumes; vollist && !(res = (vollist->Process == port));
  783.           vollist = vollist->Next);
  784.     ReleaseSemaphore(&muBase->VolumesSem);
  785.  
  786.     return(res);
  787. }
  788.  
  789.  
  790.    /*
  791.     *        Format and dump a string to the Log File
  792.     */
  793.  
  794. void VLogF(STRPTR fmt, LONG *argv)
  795. {
  796.     BPTR file;
  797.     char date[LEN_DATSTRING];
  798.     char time[LEN_DATSTRING];
  799.     struct DateTime dt;
  800.     LONG args[2];
  801.  
  802.     CurrentDir(ConfigDirLock);
  803.     if (file = Open(LogFileName, MODE_READWRITE)) {
  804.         if (Seek(file, 0, OFFSET_END) != -1) {
  805.             DateStamp(&dt.dat_Stamp);
  806.             dt.dat_Format = FORMAT_DOS;
  807.             dt.dat_Flags = NULL;
  808.             dt.dat_StrDay = NULL;
  809.             dt.dat_StrDate = date;
  810.             dt.dat_StrTime = time;
  811.             DateToStr(&dt);
  812.             args[0] = (LONG)date;
  813.             args[1] = (LONG)time;
  814.             VFPrintf(file, "%s, %s: ", args);
  815.             VFPrintf(file, fmt, argv);
  816.             FPutC(file, '\n');
  817.         }
  818.         Close(file);
  819.     }
  820. }
  821.  
  822.  
  823.     /*
  824.      *        'Safe' FGets
  825.      *
  826.      *        Prevents synchronization problems on startup
  827.      */
  828.  
  829. static STRPTR SafeFGets(BPTR fh, STRPTR buf, ULONG len)
  830. {
  831.     STRPTR res;
  832.     int i;
  833.  
  834.     if (!(res = FGets(fh, buf, len)))
  835.         for (i = 1; !res && (i < 10); i++) {
  836.             Delay(25);
  837.             res = FGets(fh, buf, len);
  838.         }
  839.     return(res);
  840. }
  841.